#ifndef __X_STREAM_H__
#define __X_STREAM_H__

struct StreamMem
{
	U8*			byBuf;
	U32			dwSize;
	U32			dwUsedSize;

	StreamMem()
	{
		byBuf = NULL;
		dwSize = 0;
		dwUsedSize = 0;
	}
	void ReUse()
	{
		dwUsedSize = 0;
	}
	StreamMem(U32 dwS)
	{
		byBuf = new U8[dwS];
		dwSize = 0;
		dwUsedSize = 0;
		if(byBuf)
		{
			dwSize = dwS;
		}
	}
	~StreamMem()
	{
		if(byBuf)
		{
			delete[] byBuf;
			byBuf = NULL;
		}
		dwSize = 0;
		dwUsedSize = 0;
	}
};

class CGsStream
{
public:
	CGsStream(U8 * pData  = NULL, U32 nCurrentLen = 0, U32 nMaxLen = 0);
	CGsStream(StreamMem* pStreamMem);
	~CGsStream(void);

	// insertion operations
	CGsStream& operator<<(U8 value);
	CGsStream& operator<<(U16 value);
	CGsStream& operator<<(U32 value);
	CGsStream& operator<<(U64 value);
	CGsStream& operator<<(F32 value);
	CGsStream& operator<<(F64 value);

	CGsStream& operator<<(S8 value);
	CGsStream& operator<<(S16 value);
	CGsStream& operator<<(S32 value);
	CGsStream& operator<<(S64 value);

	CGsStream& operator<<(S8* value);
	CGsStream& operator<<(bool value);

	// extraction operations
	CGsStream& operator>>(U8& value);
	CGsStream& operator>>(U16& value);
	CGsStream& operator>>(U32& value);
	CGsStream& operator>>(U64& value);
	CGsStream& operator>>(F32& value);
	CGsStream& operator>>(F64& value);

	CGsStream& operator>>(S8& value);
	CGsStream& operator>>(S16& value);
	CGsStream& operator>>(S32& value);
	CGsStream& operator>>(S64& value);

	CGsStream& operator>>(S8* value);
	CGsStream& operator>>(bool& value);

	BOOL Put(void * pData, U32 nLen); 
	BOOL Get(void * pDes,  U32 nLen);

	U8* GetDataPtr()
	{
		return m_pData;
	}

	U32 GetSize()
	{
		return m_nCurrentSize;
	}

	U32 GetTotalSize()
	{
		return m_nTotalSize;
	}

	BOOL IsOverFlow()
	{ 
		return m_bOverFlow; 
	}

	U8* GetCurReadPos()
	{
		return m_pData + m_iReadCursor;
	}

	U8* GetCurWritePos()
	{
		return m_pData + m_iWriteCursor;
	}

	U32 GetUnReadSize()
	{
		return m_nCurrentSize - m_iReadCursor;
	}

	U32 GetBufLeftSize()
	{
		return m_nTotalSize - m_iWriteCursor;
	}

	BOOL CanAppendData(U32 dwSize)
	{
		return (m_nCurrentSize + dwSize) < m_nTotalSize;
	}

	void Init(void);

	StreamMem* ReAlloc(StreamMem& Src);
	StreamMem* ReInit(StreamMem* pSrc);

	CGsStream(const CGsStream& Src);
	void operator=(const CGsStream& Src);

	StreamMem* getStreamMem() {return m_pStreamMem;}
protected:

protected:
	U8				*m_pData; 
	U32				m_iReadCursor,
					m_iWriteCursor;
	U32				m_nTotalSize,
					m_nCurrentSize;
	BOOL			m_bOverFlow;
	StreamMem		*m_pStreamMem;
public:
	static	BOOL	m_bBigEndian; // net stream is big-endian
};

class xStream : public CGsStream
{
public:
	xStream(U32 dwSize);
	~xStream();

	U32 Shift(U32 dwSize);
	BOOL AddWriteSize(U32 dwSize);
};

BOOL check_big_endian();

#endif //__X_STREAM_H__